package com.freeter.modules.gjs.service.impl;

import com.freeter.modules.gjs.config.FileWatcherConfig;
import com.freeter.modules.gjs.service.FileWatcherService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.io.IOException;
import java.nio.file.*;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

/**
 * 文件监控服务实现类
 * 负责监控指定目录下的文件变化，并委托给业务逻辑处理器处理
 */
@Service
public class FileWatcherServiceImpl implements FileWatcherService {
    
    private static final Logger logger = LoggerFactory.getLogger(FileWatcherServiceImpl.class);
    
    @Autowired
    private FileWatcherConfig config;
    
    @Autowired
    private BusinessLogicProcessorForFile businessLogicProcessor;
    
    @Value("${filewatcher.calc-ticket-folder:./calc_tickets}")
    private String calcTicketFolder;
    
    @Value("${filewatcher.watch-interval:1000}")
    private long watchInterval;
    
    private WatchService watchService;
    private Map<WatchKey, Path> keys;
    private ExecutorService executorService;
    private volatile boolean running = false;
    
    @PostConstruct
    public void init() {
        try {
            // 设置业务逻辑处理器的目录
            businessLogicProcessor.setCalcTicketFolder(calcTicketFolder);
            
            // 创建目录
            createDirectories();
            
            // 启动文件监控
            startFileWatcher();
        } catch (Exception e) {
            logger.error("文件监控服务初始化失败", e);
        }
    }
    
    @PreDestroy
    public void destroy() {
        stopFileWatcher();
    }
    
    @Override
    public void startFileWatcher() {
        if (running) {
            logger.warn("文件监控服务已在运行中");
            return;
        }
        
        try {
            watchService = FileSystems.getDefault().newWatchService();
            keys = new HashMap<>();
            executorService = Executors.newSingleThreadExecutor();
            
            // 注册监控目录
            registerDirectories();
            
            // 启动监控线程
            running = true;
            executorService.submit(this::watchLoop);
            
            logger.info("文件监控服务已启动，监控目录: {}", calcTicketFolder);
            
        } catch (IOException e) {
            logger.error("启动文件监控服务失败", e);
            throw new RuntimeException("启动文件监控服务失败", e);
        }
    }
    
    @Override
    public void stopFileWatcher() {
        if (!running) {
            logger.warn("文件监控服务未在运行");
            return;
        }
        
        running = false;
        
        if (executorService != null) {
            executorService.shutdown();
            try {
                if (!executorService.awaitTermination(10, TimeUnit.SECONDS)) {
                    executorService.shutdownNow();
                }
            } catch (InterruptedException e) {
                executorService.shutdownNow();
                Thread.currentThread().interrupt();
            }
        }
        
        if (watchService != null) {
            try {
                watchService.close();
            } catch (IOException e) {
                logger.error("关闭WatchService失败", e);
            }
        }
        
        keys.clear();
        logger.info("文件监控服务已停止");
    }
    
    @Override
    public boolean isRunning() {
        return running;
    }
    
    /**
     * 创建必要的目录
     */
    private void createDirectories() throws IOException {
        String[] dirs = {"gr", "transaction", "transfer_request", "damage_report"};
        for (String dir : dirs) {
            Path dirPath = Paths.get(calcTicketFolder, dir);
            if (!Files.exists(dirPath)) {
                Files.createDirectories(dirPath);
                logger.info("创建目录: {}", dirPath);
            }
        }
    }
    
    /**
     * 注册监控目录
     */
    private void registerDirectories() throws IOException {
        String[] dirs = {"gr", "transaction", "transfer_request", "damage_report"};
        for (String dir : dirs) {
            Path dirPath = Paths.get(calcTicketFolder, dir);
            registerDirectory(dirPath);
        }
    }
    
    /**
     * 注册单个目录监控
     */
    private void registerDirectory(Path dir) throws IOException {
        WatchKey key = dir.register(watchService, StandardWatchEventKinds.ENTRY_CREATE);
        keys.put(key, dir);
        logger.info("注册目录监控: {}", dir);
    }
    
    /**
     * 监控循环
     */
    private void watchLoop() {
        while (running) {
            WatchKey key;
            try {
                key = watchService.take();
            } catch (InterruptedException e) {
                if (running) {
                    logger.error("监控线程被中断", e);
                }
                break;
            }
            
            Path dir = keys.get(key);
            if (dir == null) {
                logger.warn("未知的WatchKey");
                continue;
            }
            
            for (WatchEvent<?> event : key.pollEvents()) {
                WatchEvent.Kind<?> kind = event.kind();
                
                if (kind == StandardWatchEventKinds.OVERFLOW) {
                    continue;
                }
                
                WatchEvent<Path> ev = (WatchEvent<Path>) event;
                Path fileName = ev.context();
                Path fullPath = dir.resolve(fileName);
                
                logger.info("检测到文件变化: {} - {}", kind.name(), fullPath);
                
                // 根据目录类型处理文件
                String dirName = dir.getFileName().toString();
                switch (dirName) {
                    case "gr":
                        businessLogicProcessor.processGrFile(fullPath);
                        break;
                    case "transaction":
                        businessLogicProcessor.processTransactionFile(fullPath);
                        break;
                    case "transfer_request":
                        businessLogicProcessor.processTransferRequestFile(fullPath);
                        break;
                    case "damage_report":
                        businessLogicProcessor.processDamageReportFile(fullPath);
                        break;
                    default:
                        logger.warn("未知的目录类型: {}", dirName);
                }
            }
            
            if (!key.reset()) {
                keys.remove(key);
                if (keys.isEmpty()) {
                    break;
                }
            }
        }
    }
    
    /**
     * 实现接口方法 - 处理收货单文件
     */
    @Override
    public void processGrFile(Path filePath) {
        businessLogicProcessor.processGrFile(filePath);
    }
    
    /**
     * 实现接口方法 - 处理交易文件
     */
    @Override
    public void processTransactionFile(Path filePath) {
        businessLogicProcessor.processTransactionFile(filePath);
    }
    
    /**
     * 实现接口方法 - 处理调拨申请文件
     */
    @Override
    public void processTransferRequestFile(Path filePath) {
        businessLogicProcessor.processTransferRequestFile(filePath);
    }
    
    /**
     * 实现接口方法 - 处理损坏报告文件
     */
    @Override
    public void processDamageReportFile(Path filePath) {
        businessLogicProcessor.processDamageReportFile(filePath);
    }
} 